﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.VisualStudio.Modeling.Diagrams;
using System.Drawing;
using Microsoft.VisualStudio.Modeling;
using devtm.AutoMapper.CustomCode.Shapes;
using CodeDomHelper.Types;
using CSharpParser.SCharpType;
using Microsoft.RestrictedUsage.CSharp.Semantics;
using devtm.AutoMapper.CustomCode.Helpers;

namespace devtm.AutoMapper
{
    
    public partial class MapperShape
    {




        private bool CtrlPressed = false;


        /// <summary>
        /// Gets the child compartment shape and verifies whether it can resize its parent compartment shape.
        /// </summary>
        /// <value></value>
        /// <returns>true if a child compartment shape can resize its parent compartment shape; otherwise, false.
        /// </returns>
        public override bool AllowsChildrenToResizeParent
        {
            get
            {
                // Overridden to return false so that the visual layout issue is solved, where a shape with a connector that "has custom source"
                // resizes to make the source shape wider until it reaches the edge of the referenced shape.
                // See http://social.msdn.microsoft.com/Forums/en-US/vsx/thread/4cc74f9e-1949-43ba-8407-934f6664167d.
                // It is applied to the base class here so that all inheriting compartment shapes automatically have this fix applied.
                return false;
            }
        }


        protected override void InitializeShapeFields(IList<ShapeField> shapeFields)
        {

            base.InitializeShapeFields(shapeFields);

        }

        
        public override void OnKeyDown(DiagramKeyEventArgs e)
        {
            base.OnKeyDown(e);
            CtrlPressed = e.Control;


            if (e.KeyCode == System.Windows.Forms.Keys.F12)

                try
                {


                    foreach (var item in e.TargetItem.RepresentedElements)
                    {

                        ItemMap itemMap = item as ItemMap;
                        if (itemMap != null)
                        {

                            var mapper = itemMap.Mapper.MappingModel.FindMapperFor(itemMap);
                            if (mapper != null)
                            {

                                MapperShape mm = PresentationViewsSubject.GetPresentation(mapper).FirstOrDefault() as MapperShape;

                                Microsoft.VisualStudio.Modeling.Diagrams.Diagram diagram = mm.Diagram;

                                if (diagram != null)
                                {

                                    DiagramView diagramClientView = diagram.ActiveDiagramView;

                                    if ((diagramClientView != null))
                                    {

                                        var aa = new DiagramItem(mm);

                                        if (mm.CanFocus)
                                            diagramClientView.Selection.FocusedItem = aa;

                                        diagramClientView.DiagramClientView.EnsureVisible(mm.AbsoluteBoundingBox, mm.EnsureVisiblePreference);
                                        diagramClientView.Selection.Set(diagramClientView.Selection.FocusedItem);

                                    }

                                }

                                break;

                            }

                        }
                    }


                }
                catch (Exception ex)
                {

                }

        }

        public override void OnKeyUp(DiagramKeyEventArgs e)
        {
            base.OnKeyUp(e);
            CtrlPressed = e.Control;
        }

        public override void OnDoubleClick(DiagramPointEventArgs e)
        {
            base.OnDoubleClick(e);

            using (CustomTypeRepository repository = CustomTypeRepository.Instance(this.Store, false))
            {

                foreach (var itemMAP in e.HitDiagramItem.RepresentedElements)
                {

                    ItemMap itemMap = itemMAP as ItemMap;

                    if (itemMap != null)
                    {

                        string memberName = CtrlPressed ? itemMap.TargetName : itemMap.SourceName;

                        TypeExpression typeExpression = null;
                        if (CtrlPressed)
                            typeExpression = TypeExpression.Analyse(itemMap.Mapper.MappingDestination.TypeElement.AssemblyQualifiedName);
                        else
                            typeExpression = TypeExpression.Analyse(itemMap.Mapper.MappingSource.TypeElement.AssemblyQualifiedName);


                        var type = repository.GetType(typeExpression);
                        if (type != null)
                        {
                            var member1 = type.GetMembers(memberName).FirstOrDefault();
                            if (member1 != null)
                            {

                                var declaringMember = (member1 as Mono.Cecil.IMember).DeclaringType.Resolve();

                                if (declaringMember != null)
                                {
                                    string assName = declaringMember.Module.Assembly.Name.Name;

                                    devtm.Editor.TypeSelector.ParsingSolution.Project prj = Helpers.FindProject(this.Store, assName);
                                    if (prj != null)
                                    {

                                        var project = prj.Source;
                                        if (project != null)
                                        {
                                            CSharpType sharpType = Parser.GetType(project, typeExpression.Namespace, typeExpression.Name);
                                            if (sharpType != null)
                                            {
                                                var member = sharpType.GetMember(memberName);
                                                if (member != null)
                                                    member.NavigateToSourceLocation();
                                            }
                                        }


                                    }
                                }

                            }
                        }
                    }


                }

            }

        }

        protected override void InitializeDecorators(global::System.Collections.Generic.IList<ShapeField> shapeFields, global::System.Collections.Generic.IList<Decorator> decorators)
        {

            base.InitializeDecorators(shapeFields, decorators);

            //ShapeField field2 = ShapeElement.FindShapeField(shapeFields, "RefreshDecorator1");
            RefreshField field2 = new RefreshField("RefreshDecorator1");
            Decorator decorator2 = new ShapeDecorator((ShapeField)field2, ShapeDecoratorPosition.OuterTopLeft, new PointD(0, 0));
            decorators.Add(decorator2);

            //ShapeField field2 = ShapeElement.FindShapeField(shapeFields, "RefreshDecorator1");
            PineField field3 = new PineField("PineDecorator1");
            Decorator decorator3 = new ShapeDecorator((ShapeField)field3, ShapeDecoratorPosition.OuterTopLeft, new PointD(0.25, 0));
            decorators.Add(decorator3);
            
        }
     
  

        protected override CompartmentMapping[] GetCompartmentMappings(Type melType)
        {
           
            CompartmentMapping[] mappings = base.GetCompartmentMappings(melType);

            foreach (ElementListCompartmentMapping mapping in mappings)
            {
                mapping.ImageGetter = CompartmentImageProvider;
                
            }
            
            return mappings;

        }


        private Image CompartmentImageProvider(ModelElement element)
        {

            ItemMap item = element as ItemMap;

            if (item == null)
                return devtm.AutoMapper.Properties.Resources.None;

            if (!item.Enable)
                return devtm.AutoMapper.Properties.Resources.interdit;

            else if (item.SourceName == "this")
                return devtm.AutoMapper.Properties.Resources.Class162;

            switch (item.TypeCast)
            {

                case CastType.Custom:
                    return devtm.AutoMapper.Properties.Resources.method16;


                case CastType.Map:

                    if (string.IsNullOrEmpty(item.ExternalModelDocument))
                    {
                        var mapper2 = item.Mapper.MappingModel.FindMapperFor(item);

                        if (mapper2 == null)
                        {

                            string target = item.TargetType;
                            var t = BuildTypeExpression.Analyse(target);
                            var t1 = t.IsGeneric
                                ? t.SubType.Namespace + "." + t.SubType.Name
                                : t.Namespace + "." + t.Name;

                            foreach (var type in types)
                                if (type.FullName == t1)
                                    return devtm.AutoMapper.Properties.Resources.flecheMap2;

                            return devtm.AutoMapper.Properties.Resources.flecheMap2Error;
                        }

                        return devtm.AutoMapper.Properties.Resources.flecheMap2;
                    }

                    var mapper3 = item.Mapper.MappingModel.FindExternalMapperFor(item.ExternalModelDocument);

                        if (mapper3 == null)
                            return devtm.AutoMapper.Properties.Resources.flecheMap2Error;

                        return devtm.AutoMapper.Properties.Resources.flecheMapLink;
                    
                case CastType.Array:
                case CastType.Collection:
                case CastType.List:
                case CastType.ObservableCollection:

                        if (string.IsNullOrEmpty(item.ExternalModelDocument))
                        {
                            var mapper = item.Mapper.MappingModel.FindMapperFor(item);

                            if (mapper == null)
                            {

                                string target = item.TargetType;
                                var t = BuildTypeExpression.Analyse(target);
                                var t1 = t.IsGeneric
                                    ? t.SubType.Namespace + "." + t.SubType.Name
                                    : t.Namespace + "." + t.Name;

                                foreach (var type in types)
                                    if (type.FullName == t1)
                                        return devtm.AutoMapper.Properties.Resources.flecheMap;

                                return devtm.AutoMapper.Properties.Resources.flecheMapError;
                            }

                            return devtm.AutoMapper.Properties.Resources.flecheMap;
                        }

                        var mapper4 = item.Mapper.MappingModel.FindExternalMapperFor(item.ExternalModelDocument);

                    if (mapper4 == null)
                        return devtm.AutoMapper.Properties.Resources.flecheMapError;

                    return devtm.AutoMapper.Properties.Resources.flecheMapLink;

                //case CastType.IConverter:
                //case CastType.Explicit:
                //case CastType.TypeConverter:
                //case CastType.Hashset:
                //case CastType.EnumByValue:
                //case CastType.EnumByLabel:
                //case CastType.Implicit:
                //case CastType.IValueConverter:

                case CastType.None:
                default:
                    return devtm.AutoMapper.Properties.Resources.None;

            }


        }


        private static Type[] types = new Type[] 
            { typeof(string), typeof(sbyte), typeof(byte), typeof(char)
              , typeof(short), typeof(ushort), typeof(int), typeof(uint)
              , typeof(long), typeof(ulong) , typeof(float), typeof(double)
              , typeof(Int16), typeof(Int32), typeof(Int64)                
              , typeof(UInt16), typeof(UInt32), typeof(UInt64)
              , typeof(bool), typeof(decimal)
              , typeof(sbyte?), typeof(byte?), typeof(char?)
              , typeof(short?), typeof(ushort?), typeof(int?), typeof(uint?)
              , typeof(long?), typeof(ulong?) , typeof(float?), typeof(double?)
              , typeof(Int16?), typeof(Int32?), typeof(Int64?)                
              , typeof(UInt16?), typeof(UInt32?), typeof(UInt64?)
              , typeof(bool?), typeof(decimal?)
            };


        public void MovesTypes()
        {

           
            Mapper mapper = ModelElement as Mapper;

            using (Transaction trans = mapper.Store.TransactionManager.BeginTransaction("reorder the diagram"))
            {

                foreach (BinaryLinkShape item in this.Link)
                {
                    if (item is LeftConnector)
                    {
                        LeftConnector left = item as LeftConnector;
                        TypeElementShape tl = left.FromShape as TypeElementShape;
                        tl.Location = new PointD(this.Location.X - tl.Size.Width - 1, this.Location.Y);
                    }
                    else if (item is RightConnector)
                    {
                        RightConnector right = item as RightConnector;
                        TypeElementShape tr = right.FromShape as TypeElementShape;
                        tr.Location = new PointD(this.Location.X + this.Size.Width + 1, this.Location.Y);

                    }
                }

                trans.Commit();
            }
        }


        //public bool Navigate(DiagramItem newFocusItem, SelectedShapesCollection selection)
        //{
        //    bool flag = false;
        //    if (selection == null)
        //    {
        //        return false;
        //    }
        //    if (newFocusItem != null)
        //    {
        //        if (!newFocusItem.Equals(selection.FocusedItem))
        //        {
        //            selection.FocusedItem = newFocusItem;
        //            flag = true;
        //        }
        //        Microsoft.VisualStudio.Modeling.Diagrams.Diagram diagram = this.Diagram;
        //        if (diagram != null)
        //        {
        //            DiagramView activeDiagramView = diagram.ActiveDiagramView;
        //            if ((activeDiagramView != null) && !newFocusItem.IsDiagram)
        //            {
        //                activeDiagramView.DiagramClientView.EnsureVisible(newFocusItem.AbsoluteBoundingBox, this.EnsureVisiblePreference);
        //            }
        //        }
        //    }
        //    return flag;
        //}



    }
     
    
}
